package com.mbc.hr.manager;

import java.sql.SQLException;
import java.util.List;

import javax.persistence.NoResultException;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import com.mbc.common.exception.DataDuplicationException;
import com.mbc.common.exception.ForeignConflictException;
import com.mbc.common.manager.AbstractMgr;
import com.mbc.common.param.CriteriaParams;
import com.mbc.common.utils.KeyGenerator;
import com.mbc.hr.data.AttendancePolicyDataList;
import com.mbc.hr.entities.AttendancePolicy;
import com.mbc.hr.entities.AttendancePolicyDetail;

public class AttendancePolicyMgr extends AbstractMgr {
	public AttendancePolicyMgr() {

	}
	public AttendancePolicyMgr(String sessionID) {
		this.sessionId = sessionID;
	}
	public void create(AttendancePolicy attendancePolicy) throws Exception {
		openConnection();
		try {
			beginTransaction();
			long l_key = KeyGenerator.generateKey(entityManager);
			//Data binding required server side values
			//long l_key = Long.parseLong(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));

			attendancePolicy.setAttendancePolicyID(l_key);
			entityManager.persist(attendancePolicy);

			for (AttendancePolicyDetail l_detail : attendancePolicy.getDetails()) {
				l_detail.setAttendancePolicyID(l_key);
				entityManager.persist(l_detail);
			}
			commitTransaction();
		} catch (Exception e) {
			rollbackTransaction();
			if(DataDuplicationException.isUniqueKyeError(e))
				throw new DataDuplicationException(e.getMessage());
			else
				throw e;
		} finally {
			closeConnection();
		}
	}
	public void update(AttendancePolicy attendancePolicy) throws Exception {
		openConnection();
		try {
			beginTransaction();

			entityManager.merge(attendancePolicy);

			entityManager.createNamedQuery("AttendancePolicyDetail.deleteByPolicyID")
					.setParameter("policyID", attendancePolicy.getAttendancePolicyID()).executeUpdate();
			for (AttendancePolicyDetail l_detail : attendancePolicy.getDetails()) {
				l_detail.setAttendancePolicyID(attendancePolicy.getAttendancePolicyID());
				entityManager.persist(l_detail);
			}

			commitTransaction();
		} catch (Exception e) {
			rollbackTransaction();
			throw e;
		} finally {
			closeConnection();
		}
	}
	public void delete(long attendancePolicyID) throws Exception {
		openConnection();
		try {
			beginTransaction();
			entityManager.createNamedQuery("AttendancePolicyDetail.deleteByPolicyID")
				.setParameter("policyID", attendancePolicyID).executeUpdate();
			AttendancePolicy l_attendancePolicy = entityManager.find(AttendancePolicy.class, attendancePolicyID);
			entityManager.remove(l_attendancePolicy);
			commitTransaction();
		} catch (Exception e) {
			rollbackTransaction();
			if (e.getCause().getCause().getCause() instanceof SQLException) {
				if (ForeignConflictException.FOREIGN_CONFLICT_ERROR_CODE == ((SQLException) e.getCause().getCause()
						.getCause()).getErrorCode())
					throw new ForeignConflictException(e);
				else
					throw e;
			} else
				throw e;
		} finally {
			closeConnection();
		}
	}

	public AttendancePolicy find(long attendancePolicyID) throws Exception {
		openConnection();
		try {
			AttendancePolicy l_attendancePolicy = entityManager.find(AttendancePolicy.class, attendancePolicyID);
			if (l_attendancePolicy != null) {
				l_attendancePolicy.setDetails(entityManager
						.createNamedQuery("AttendancePolicyDetail.findByPolicyID", AttendancePolicyDetail.class)
						.setParameter("policyID", attendancePolicyID).getResultList());
			}
			return l_attendancePolicy;
		} catch (Exception e) {
			throw e;
		} finally {
			closeConnection();
		}
	}

	public List<AttendancePolicy> findAll() throws Exception {
		openConnection();
		try {
			return entityManager.createNamedQuery("AttendancePolicy.findAll", AttendancePolicy.class).getResultList();
		} catch (Exception e) {
			throw e;
		} finally {
			closeConnection();
		}
	}

	public List<AttendancePolicyDetail> findDetails(long attendancePolicyID) throws Exception {
		openConnection();
		try {
			return entityManager
					.createNamedQuery("AttendancePolicyDetail.findByPolicyID", AttendancePolicyDetail.class)
					.setParameter("policyID", attendancePolicyID).getResultList();
		} catch (Exception e) {
			throw e;
		} finally {
			closeConnection();
		}
	}

	public AttendancePolicyDataList getAttendancePolicy(CriteriaParams cri) throws Exception {
		openConnection();
		try {
			CriteriaBuilder l_criBuilder = entityManager.getCriteriaBuilder();
			CriteriaQuery<AttendancePolicy> l_cri = l_criBuilder.createQuery(AttendancePolicy.class);
			Root<AttendancePolicy> l_root = l_cri.from(AttendancePolicy.class);
			l_cri.select(l_root);
			Predicate l_Predicate = l_criBuilder.or(
					l_criBuilder.like(l_root.<String> get("policyCode"), "%" + cri.getKeyword() + "%"),
					l_criBuilder.like(l_root.<String> get("description"), "%" + cri.getKeyword() + "%"));
			l_cri.where(l_Predicate);

			List<AttendancePolicy> l_entityList = entityManager.createQuery(l_cri)
					.setFirstResult(cri.getIndex())
					.setMaxResults(cri.getSize())
					.getResultList();

			AttendancePolicyDataList l_dataList = new AttendancePolicyDataList();
			l_dataList.setEntityList(l_entityList);

			if (cri.getIndex() == 0) {
				CriteriaQuery<Long> l_countQuery = l_criBuilder.createQuery(Long.class);
				l_root = l_countQuery.from(AttendancePolicy.class);
				l_countQuery.select(l_criBuilder.count(l_root));
				l_countQuery.where(l_Predicate);
				l_dataList.setTotalRecord(entityManager.createQuery(l_countQuery).getSingleResult());
			}

			return l_dataList;
		} catch (Exception e) {
			throw e;
		} finally {
			closeConnection();
		}
	}
	
	public AttendancePolicyDetail getAttendaccePolicyDetailByEmployeeIdNDay(long employeeID, int day)throws Exception{
		openConnection();
		try {
			AttendancePolicyDetail l_detail = null;
			try {
				l_detail = entityManager.createNamedQuery("AttendancePolicyDetail.getPolicyDetailByEmployeeIdNDay", AttendancePolicyDetail.class)
						.setParameter("employeeID", employeeID)
						.setParameter("day", day)
						.getSingleResult();
			} catch (NoResultException innerEx) {}
			return l_detail;
		} catch (Exception e) {
			throw e;
		} finally {
			closeConnection();
		}
	}
	
	public List<AttendancePolicyDetail> getEmployeeAttendancePolicyDetails(long employeeID)throws Exception{
		openConnection();
		try {
			return entityManager.createNamedQuery("AttendancePolicyDetail.getPolicyDetailByEmployeeID", AttendancePolicyDetail.class)
					.setParameter("employeeID", employeeID)
					.getResultList();
		} catch (Exception e) {
			throw e;
		} finally {
			closeConnection();
		}
	}
}
